package com.qjdchina.sku.biz.impl;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.qjdchina.commons.result.Result;
import com.qjdchina.sku.biz.VerifyCodeManager;
import com.qjdchina.sku.biz.YunpianSmsManager;
import com.qjdchina.sku.model.vo.VerifyCodeVo;
import com.qjdchina.sku.service.enums.SkuResultCode;
import com.qjdchina.sku.util.DateUtil;
import com.qjdchina.sku.util.ImgVerifyCodeUtils;
import com.qjdchina.sku.util.ProductModeUtil;
import com.qjdchina.sku.util.SMSVerifyCodeUtils;


/**
 * 
 * 类名:VerifyCodeManagerImpl 功能:验证码生成及验证 日期: 2016年1月20日 上午10:45:02
 * 
 * @author wangzheng
 * @version 1.0.0
 * @since JDK 1.7
 * @see
 */
@Service
public class VerifyCodeManagerImpl implements VerifyCodeManager {

	private static final Logger LOGGER = LoggerFactory.getLogger(VerifyCodeManagerImpl.class);
	
	@Autowired
	private YunpianSmsManager yunpianSmsManager;

	@Override
	public Result<VerifyCodeVo> sendVerificationCode(String phone, long tplId) {

		try {
			if (ProductModeUtil.isOnlineMode()) {
				// 生成验证码
				String code = SMSVerifyCodeUtils.generateVerifyCode(6);
				Map<String, String> map = new HashMap<String, String>();
				map.put("code", code);
				// 发送短信
				Result<String> sendResult = yunpianSmsManager.sendWithTemplate(tplId, map, phone);
				// 发送成功
				if (sendResult.isSuccess()) {
					VerifyCodeVo vcv = new VerifyCodeVo();
					vcv.setVerifyCode(code);
					vcv.setDate(Calendar.getInstance().getTime());
					vcv.setPhone(phone);
					return new Result<VerifyCodeVo>(vcv);
				} else {
					return new Result<VerifyCodeVo>(SkuResultCode.SKU_FNT_SEND_SMS_FAIL);
				}
			} else {
				// 非生产环境，使用手机号的末6位
				String code = org.apache.commons.lang.StringUtils.substring(phone, -6);
				// log for test
				VerifyCodeVo vcv = new VerifyCodeVo();
				vcv.setVerifyCode(code);
				vcv.setDate(Calendar.getInstance().getTime());
				vcv.setPhone(phone);
				LOGGER.info("[SMS_V_CODE]" + code);
				return new Result<VerifyCodeVo>(vcv);
			}

		} catch (Exception e) {
			LOGGER.warn("send SMS fail...", e);
			return new Result<VerifyCodeVo>(SkuResultCode.SKU_FNT_SEND_SMS_FAIL);
		}
	}

	@Override
	public Result<String> checkInputVerificationCode(String phone, String input, VerifyCodeVo verifyCodeVo) {

		if (StringUtils.isEmpty(phone)) {
			LOGGER.warn("user input phone is null");
			return new Result<String>(SkuResultCode.PHONE_NOT_EMPTY);
		}

		if (StringUtils.isEmpty(input)) {
			LOGGER.warn("user input validation code is null ");
			return new Result<String>(SkuResultCode.SKU_FNT_VERIFY_CODE_NOT_EMPTY);
		}

		if (null == verifyCodeVo) {
			LOGGER.warn("the verifyCodeVo doesn't exist in session");
			return new Result<String>(SkuResultCode.SKU_FNT_VERIFY_CODE_PHONE_FAILURE);
		}

		if (StringUtils.isEmpty(verifyCodeVo.getVerifyCode())) {
			LOGGER.warn("the VerifyCode is null for verifyCodeVo");
			return new Result<String>(SkuResultCode.SKU_FNT_VERIFY_CODE_PHONE_FAILURE);
		}
		if (StringUtils.isEmpty(verifyCodeVo.getPhone())) {
			LOGGER.warn("the Phone is null for verifyCodeVo");
			return new Result<String>(SkuResultCode.SKU_FNT_VERIFY_CODE_PHONE_FAILURE);
		}
		if (StringUtils.isEmpty(verifyCodeVo.getDate())) {
			LOGGER.warn("the Date is null for verifyCodeVo");
			return new Result<String>(SkuResultCode.SKU_FNT_VERIFY_CODE_PHONE_FAILURE);
		}

		// 1.验证 用户输入的时间验证码的时间 是否超过 系统发送验证码的时间,5分钟有效期
		Date currentDate = Calendar.getInstance().getTime();
		Date vcDate = verifyCodeVo.getDate();
		if (DateUtil.isBefore(currentDate, vcDate, 300)) {
			LOGGER.warn("validation code timed out");
			return new Result<String>(SkuResultCode.SKU_FNT_VERIFY_CODE_PHONE_FAILURE);
		}

		// 2.验证用户手机号是否一致
		if (!phone.equals(verifyCodeVo.getPhone())) {
			LOGGER.warn("the twice entered phone number is inconsistent, the first one is :" + verifyCodeVo.getPhone()
					+ " the current one is :" + phone);
			return new Result<String>(SkuResultCode.SKU_FNT_VERIFY_CODE_PHONE_FAILURE);
		}

		// 3.验证用户输入的验证码是否正确
		if (!input.equals(verifyCodeVo.getVerifyCode())) {
			LOGGER.warn("validation code isn't correct");
			return new Result<String>(SkuResultCode.SKU_FNT_VERIFY_CODE_INPUT_ERROR);
		}

		return new Result<String>("success");
	}

	@Override
	public Result<VerifyCodeVo> generateCode(int verifySize) {

		// 生成验证码
		String verifyCode = ImgVerifyCodeUtils.generateVerifyCode(verifySize);

		try {
			if (!ProductModeUtil.isOnlineMode()) {
				LOGGER.info("[verifyCode]===" + verifyCode);
			}
		} catch (IOException e) {
			LOGGER.warn("get onlineMode fail...", e);
		}

		VerifyCodeVo vcv = new VerifyCodeVo();
		vcv.setVerifyCode(verifyCode);
		vcv.setDate(Calendar.getInstance().getTime());

		return new Result<VerifyCodeVo>(vcv);
	}

	@Override
	public void outputImage(int w, int h, OutputStream os, String code) throws IOException {
		// 生成图片
		ImgVerifyCodeUtils.outputImage(w, h, os, code);
	}

	@Override
	public Result<String> checkImgVerificationCode(String code, String inputCode, Date imgDate) {

		if (StringUtils.isEmpty(inputCode)) {
			LOGGER.warn("user input identifying is null");
			return new Result<String>(SkuResultCode.SKU_FNT_IMG_VERIFY_CODE_NOT_EMPTY);
		}

		if (StringUtils.isEmpty(code)) {
			LOGGER.warn("the code doesn't exist in session");
			return new Result<String>(SkuResultCode.SKU_FNT_IMG_VERIFY_CODE_FAILURE);
		}

		if (StringUtils.isEmpty(imgDate)) {
			LOGGER.warn("the imgDate doesn't exist in session");
			return new Result<String>(SkuResultCode.SKU_FNT_IMG_VERIFY_CODE_FAILURE);
		}

		// 1.验证 用户输入的时间验证码的时间 是否超过 系统发送验证码的时间,3分钟有效期
		Date currentDate = Calendar.getInstance().getTime();
		if (DateUtil.isBefore(currentDate, imgDate, 180)) {
			LOGGER.warn("validation code timed out");
			return new Result<String>(SkuResultCode.SKU_FNT_IMG_VERIFY_CODE_FAILURE);
		}

		// 全部转为小写进行比较
		String v = code.toLowerCase();
		String i = inputCode.toLowerCase();
		if (!v.equals(i)) {
			LOGGER.warn("validation code isn't correct");
			return new Result<String>(SkuResultCode.SKU_FNT_VERIFY_CODE_INPUT_ERROR);
		}

		return new Result<String>("success");
	}

}
